﻿using System;
using System.Runtime.CompilerServices;
using UnityEngine;
using XLua.Cast;

namespace Yoozoo.Modules.InnerCity
{
    public class PatrolAction : ActionBase
    {
        private const float watchTime = 3.0f;
        
        private int fromIndex;
        private int toIndex;

        private float idleTime;

        private float moveTime;
        private float hasMoveTime;

        private bool isWalking;

        public bool IsExecuteMove
        {
            get => this.isWalking;
        }

        protected override StateAction state
        {
            get => StateAction.Patrol;
        }

        public override void Init(CityUnit owner)
        {
            base.Init(owner);
        }

        public override void Enter(object args = null)
        {
            Debug.Log("进入了巡逻状态");
            
            this.fromIndex = 0;
            this.toIndex = this.fromIndex + 1;
            StartIdle();
        }

        public override void Play()
        {
            this.idleTime -= Time.deltaTime;
            if (idleTime > 0)
                return;

            if (!isWalking)
            {
                StartWalk();
                return;;
            }

            if (this.owner.IsStopMove)
                return;
            
            this.hasMoveTime += Time.deltaTime;
            var percent = this.hasMoveTime / this.moveTime;
            if (percent > 1)
                percent = 1;

            var a = this.owner.MoveWayPoints[this.fromIndex];
            var b  = this.owner.MoveWayPoints[this.toIndex];
            this.owner.SetPosition(Mathf.Lerp(a.x, b.x, percent), 0, Mathf.Lerp(a.z, b.z, percent));
            if (percent < 1)
                return;
            
            this.OnStageArrive();
        }

        public override void Exit()
        {
            Debug.Log("退出了巡逻状态");
            
            base.Exit();
        }

        private void StartWalk()
        {
            this.isWalking = true;
            RefreshMoveTime();
            ChangeDirection();
            if (!this.owner.IsStopMove)
                this.owner.PlayWalkAni();
        }

        private void StartIdle()
        {
            this.isWalking = false;
            this.idleTime = watchTime;
            this.owner.PlayIdleAni();
        }

        private void OnStageArrive()
        {
            if (this.toIndex > this.fromIndex)
            {
                this.toIndex++;
                if (this.toIndex >= this.owner.MoveWayPoints.Count)
                {
                    this.fromIndex = this.owner.MoveWayPoints.Count - 1;
                    this.toIndex = this.fromIndex - 1;
                    StartIdle();
                    return;
                }

                this.fromIndex++;
                RefreshMoveTime();
                ChangeDirection();
                return;
            }

            this.toIndex--;
            if (this.toIndex < 0)
            {
                this.fromIndex = 0;
                this.toIndex = this.fromIndex + 1;
                StartIdle();
                return;
            }

            this.fromIndex--;
            RefreshMoveTime();
            ChangeDirection();
        }

        private void RefreshMoveTime()
        {
            var disX = this.owner.MoveWayPoints[this.fromIndex].x - this.owner.MoveWayPoints[this.toIndex].x;
            var disZ = this.owner.MoveWayPoints[this.fromIndex].z - this.owner.MoveWayPoints[this.toIndex].z;
            var dis = Mathf.Sqrt(disX * disX + disZ * disZ);
            this.moveTime = dis / CityUnitMgr.unitWalkSpeed;
            this.hasMoveTime = 0;
        }

        private void ChangeDirection()
        {
            var isReturn = this.toIndex < this.fromIndex;
            var vec = isReturn ? this.owner.MoveWayPoints[this.fromIndex] : this.owner.MoveWayPoints[this.toIndex];
            if (vec.y == 0)
                return;

            var x = vec.y / 1000;
            var z = vec.y % 1000;
            if (x > 100)
                x = -(x - 100);

            if (z > 100)
                z = -(z - 100);

            
            var r = this.owner.Rotation;
            r.x = isReturn ? -x : x;
            r.z = isReturn ? -z : z;
            this.owner.SetRotation(r);
        }
    }
}